import 'dart:convert';
import 'dart:io';

import 'package:meta/meta.dart';

void main() {}

typedef MessageCallback = void Function(String message);

class SocketIOManager {
  final String host;

  final int port;

  final String delimit;

  final Duration timeout;

  Duration retryInterval;
  
  int _count = 0;

  final MessageCallback callback;

  Future _future;

  static StringBuffer _data = StringBuffer();

  SocketIOManager(this.host, this.port, this.callback,
      {@required this.delimit, this.timeout, this.retryInterval}) {
    if(this.retryInterval == null) {
      this.retryInterval = Duration(seconds: 5);
    }
    print("_构造函数 执行");
    _connect(timeout: timeout)
        .then((v) => _listenData())
        .catchError((error) => _retry(retryInterval));
  }

  Socket _socket;

  void close() {
    if(_socket != null) {
      _socket.destroy();
      _socket.close();
    }
  }

  Future<void> _connect({Duration timeout}) async {
    print("_connect 执行");
    if (_socket != null) {
      _socket.destroy();
      _socket.close();
    }

    try {
      _socket = await Socket.connect(host, port, timeout: timeout);
      print('连接建立');
      return Future.value();
    }on Exception catch(error)  {
      print("连接异常: ${error.toString()}");
      return Future.error(error.toString());
    } finally {
      if(_future != null) {
        _future = null;
      }
    }
  }

  Future<String> write(String msg) async {
    print("_write 执行");
    if(_future != null) {
      return Future.error("网络连接中");
    }
    try {
      _socket.write(msg + delimit);
      return Future.value(msg);
    } on Exception catch(error) {
      print("write error ------- ${error.toString()}");
      _retry(retryInterval);
      return Future.error(error.toString());
    }
  }

  void _listenData() {
    print("_listenData 执行");
    _socket.listen(_onData, cancelOnError: false, onError: (e) {
      print("----- 数据处理流异常: ---" + e.message);
      _retry(retryInterval);
    });
  }

  void _retry(Duration duration) {
    print("_retry 执行");
    if (_future == null) {
      print("------ 重新尝试连接 ------${DateTime.now().toLocal()}");
      _future = Future.delayed(duration, () {
        print("---开始尝试连接---");
        _connect(timeout: timeout)
            .then((v) => _listenData())
            .catchError((error) => _retry(duration));
      });
    }
  }

  void _onData(List<int> onData) {
    final String msg = utf8.decode(onData);
    _data.write(msg);
    final String data = _data.toString();
    print("data: ${data}");

    if (data.endsWith(delimit)) {
      data.split(delimit).forEach((i) {
        if (i.isNotEmpty) {
          callback(i);
        }
      });
      _data.clear();
    } else if (data.contains(delimit)) {
      final array = data.split(delimit);
      for (int i = 0; i < array.length - 1; i++) {
        String m = array[i];
        if (m.isNotEmpty) {
          callback(m);
        }
      }
      _data.clear();
      _data.write(array[array.length - 1]);
    }
  }
}
